home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 49
/
Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso
/
-serious-
/
misc
/
charmap
/
source
/
events.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-30
|
16KB
|
498 lines
/***************************************************************
** Events.c: Prends en charge la gestion des événements uti- **
** sateur. Écrit par T.Pierron **
** 14-11-1999 **
***************************************************************/
/* All the necessary includes: */
#include <Intuition/Intuition.H> /* Std datatypes */
#include <Intuition/IntuitionBase.H> /* To access ActiveScreen */
#include <Intuition/Screens.H> /* Screen information */
#include <Graphics/RastPort.H> /* Rastport info */
#include <Graphics/GfxBase.H> /* DefaultFont */
#include <Graphics/Text.H> /* struct TextFont */
#include <Libraries/Gadtools.H> /* NewMenus and NewGadget */
#include <Libraries/Commodities.H> /* Commodity datatypes */
#include <Libraries/Dos.H> /* CTRL/C signal */
#include <Devices/InputEvent.H> /* For raw keymap conversion */
#include "cmap.h"
#define CATCOMP_STRINGS /* We only need strings */
#include "cmap_strings.h" /* Support of locale.library */
/* External variables: */
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct Library *IconBase;
extern struct Window *window;
extern struct Screen *screen;
extern struct NewMenu newmenu[],*checked,*checkset;
extern struct NewWindow new_window;
extern struct TextFont *font,*newfont;
extern struct RastPort *RP;
extern struct Gadget *gad;
extern struct Menu *menu;
extern WORD xdeb,ydeb,xfin,yfin,X,Y; /* ASCII Table position */
extern UBYTE MaxWid,Font_height,Char[]; /* Font information */
extern ULONG BoxTags[],sigwin;
extern UBYTE CharsetNum;
struct TTextAttr *aslfont; /* Returned by the ASL font requester */
struct MsgPort *broker_mp = NULL; /* Commodity message port */
CxObj *broker, *filter; /* Commodity and hot-key */
CxMsg *msg; /* To collect messages */
UBYTE *StrBuf; /* Shortcut to string gadget's buffer */
struct IntuiMessage message;
struct InputEvent ie = {0,IECLASS_RAWKEY}; /* Keyboard translation map: */
BOOL IsDraw=0,PopWin=TRUE; /* State of the recessed box */
WORD NumChar; /* Selected character number */
ULONG cxsigflag=0; /* Signal bits of the commo. */
struct NewBroker newbroker = {
NB_VERSION,
MSG_COMMONAME_STR, /* String to identify this commo. */
MSG_DESCLINE1_STR,
MSG_DESCLINE2_STR,
NBU_UNIQUE | NBU_NOTIFY | /* Don't want any new commodities starting with this name. */
COF_SHOW_HIDE, /* If someone tries it, let me know */
0, 0, 0, 0
};
void Free_commodity();
/**** Initialize the message port of the commodity: ****/
BOOL Init_commodity(int argc, char *argv[])
{
UBYTE *hotkey, **ttypes;
if(broker_mp = (void *) CreateMsgPort())
{
newbroker.nb_Port = broker_mp;
cxsigflag = 1L << broker_mp->mp_SigBit;
ttypes = (UBYTE **) ArgArrayInit(argc, argv);
newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);
hotkey = (UBYTE *) ArgString(ttypes, "HOTKEY", "rawkey lalt control c");
/* Whould the user show immediatly the window ? */
if( strcasecmp(ArgString(ttypes, "CX_POPUP", Char), "NO")==0 ) PopWin=FALSE;
if(broker = (void *) CxBroker(&newbroker, NULL))
{
/* HotKey() is an amiga.lib function that creates a filter, sender */
/* and translate CxObject and connects them to report a hot key */
/* press and delete its input event. */
if(filter = (void *) HotKey(hotkey, broker_mp, EVT_HOTKEY))
{
AttachCxObj(broker, filter); /* Add a CxObject to another's personal list */
if(! CxObjError(filter))
ActivateCxObj(broker, 1L); /* All done! */
}
}
ArgArrayDone(); /* this amiga.lib function cleans up after ArgArrayInit() */
}
return (broker && broker_mp);
}
void Free_commodity()
{
/* DeleteCxObjAll() is a commodities.library function that not only **
** deletes the CxObject pointed to in its argument, but deletes all of **
** the CxObjects attached to it. */
if(broker)
{
DeleteCxObjAll(broker);
/* Empty the port of all CxMsgs */
while(msg = (CxMsg *)GetMsg(broker_mp))
ReplyMsg((struct Message *)msg);
}
if(broker_mp) DeletePort(broker_mp);
}
static WORD OldX=0,OldY=0,Xc=0,Yc=0;
/**** Move the sunken box while dragging the mouse with LMB down: ****/
void Handle_box()
{
extern WORD txtpen, poppen, fillpen;
extern UBYTE CharWid[];
WORD sunken=FALSE;
/* Center mouse position on top-left corner of the box: */
if(X<xdeb) X=0; else X -= (X-xdeb)%MaxWid;
if(Y<ydeb) Y=0; else Y -= (Y-ydeb)%Font_height;
/* If it isn't already drawn... */
IsDraw=PRESSED;
if(X==OldX && Y==OldY) return;
BoxTags[2] = TAG_DONE;
/* ...and inside area */
if(OldX>=xdeb && OldX<xfin && OldY>=ydeb && OldY<yfin)
{
DR:SetAPen(RP,sunken?fillpen : 0);
RectFill(RP,OldX+1,OldY+1,OldX+MaxWid-2,OldY+Font_height-2);
SetAPen(RP,sunken?poppen : txtpen);
Move(RP,OldX+(MaxWid-CharWid[NumChar]>>1),OldY+font->tf_Baseline+2);
*Char = (UBYTE) NumChar;
Text(RP,Char,1);
DrawBevelBoxA(RP,OldX,OldY,MaxWid,Font_height,BoxTags);
}
if(sunken) return; OldX=X; OldY=Y;
if(X>=xdeb && X<xfin && Y>=ydeb && Y<yfin) {
BoxTags[2] = GTBB_Recessed;
NumChar = ((X-xdeb)/MaxWid<<3)+(Y-ydeb)/Font_height;
if(CharsetNum >1) NumChar+=32;
if(CharsetNum==3 && NumChar>127) NumChar+=160-128;
sunken=TRUE; Xc=X; Yc=Y; goto DR;
} else {
NumChar=-1;
IsDraw=OUTSIDE_AREA;
}
}
/**** Move the box using the keyboard: ****/
void Handle_keyboard(UWORD code)
{
/* To prevent that keyboard doesn't disturb the mouse: */
if(IsDraw > 0 || code<76 || code>79) return;
if(Xc)
{
/* Rawkey code for arrow keys: */
switch(code)
{
case 76: Yc -= Font_height; break;
case 77: Yc += Font_height; break;
case 78: Xc += MaxWid; break;
case 79: Xc -= MaxWid; break;
}
/* Check if cursor overrun the map: */
if(Yc< ydeb) { Yc=yfin-Font_height; Xc-=MaxWid; }
if(Yc>=yfin) { Yc=ydeb; Xc+=MaxWid; }
if(Xc< xdeb) Xc=xfin-MaxWid;
if(Xc>=xfin) Xc=xdeb;
} else {
/* If cursor hasn't been moved yet: */
Xc=xdeb; Yc=ydeb;
}
X=Xc; Y=Yc;
Handle_box();
/* To prevent mouse doesn't disturb the keyboard: */
IsDraw=KEYB_CONTROL;
}
/**** Processes menus events: ****/
void Handle_menu( LONG MenuID )
{
extern struct EasyStruct Request;
/** L'auteur présente ses plus plates excuses pour ce très ***
*** mauvais exemple de programmation spaghetti. **/
switch( MenuID )
{
case 11: /* Look if the first item isn't already selected: */
if(checked == &newmenu[1]) break;
/* Take the font of the screen (Please, don't close it!): */
font = screen->RastPort.Font; goto check;
case 12: /* Ditto: */
if(checked == &newmenu[2]) break;
font = GfxBase->DefaultFont;
check: /* Menus will be reallocated, change NewMenus struct. directly: */
checked->nm_Flags &= ~CHECKED;
checked = &newmenu[ MenuID-10 ];
checked->nm_Flags |= CHECKED;
/* Change the charset depending of the font: */
Init_charset(font);
MenuID = CharsetNum+140;
goto charset;
REDOIT: MenuID = 13;
case 13: /* Open a ASL requester: */
if( aslfont = (struct TTextAttr *) open_asl() )
{
if( newfont ) CloseFont(newfont);
if( newfont=(void *)OpenDiskFont(aslfont) )
{
font = newfont;
goto check;
}
}
/* Cancel the menu selection (sorry, I don't want to use temporary variables) */
((struct MenuItem *)ItemAddress(menu,SHIFTMENU(0)+SHIFTITEM(checked-&newmenu[1])+SHIFTSUB(NOSUB)))->Flags |= CHECKED;
((struct MenuItem *)ItemAddress(menu,SHIFTMENU(0)+SHIFTITEM(2)+SHIFTSUB(NOSUB)))->Flags &= (~CHECKED);
break;
/* Changing the charset of ASCII table: */
case 141:if(checkset == &newmenu[6]) break; goto charset;
case 142:if(checkset == &newmenu[7]) break; goto charset;
case 143:if(checkset == &newmenu[8]) break;
charset: checkset->nm_Flags &= ~CHECKED;
checkset = &newmenu[ MenuID-141+6 ];
CharsetNum = MenuID-140;
checkset->nm_Flags |= CHECKED;
new_window.Title = checkset->nm_Label;
/* Now, we can reopen our window: */
goto new_win;
case 14: /* Clear the text contained in the string gadget: */
StrBuf[0]=0; RefreshGList(gad, window, NULL, 1);
break;
case 15: /* Jump to the next screen: */
if( !screen->NextScreen ) break;
screen = screen->NextScreen;
if(checked == &newmenu[1]) font = screen->RastPort.Font;
new_win: cleanup(NULL,-1);
/* If init failed, try to see if we can changed the font again: */
if( setup() ) goto REDOIT;
/* Before to move the screen, wait all it's OK: */
ScreenToFront(screen);
break;
case 16: EasyRequestArgs(window, &Request, 0, 0); break;
case 17: /* Iconify/Uniconify the window: */
ZipWindow(window);
break;
case 18: cleanup(NULL,-1); return;
case 19: cleanup(NULL,0);
}
if(window==NULL) cleanup(0,0);
}
/**** Handle all messages comming from a commo: ****/
void Handle_commo(void)
{
ULONG msgid, msgtype;
/* The signal is comming from a commodity: */
while(msg = (CxMsg *)GetMsg(broker_mp))
{
msgid = CxMsgID(msg);
msgtype = CxMsgType(msg);
ReplyMsg((struct Message *)msg);
switch(msgtype)
{
case CXM_IEVENT:
/* Display or move the window, in the front-most screen: */
if(msgid == EVT_HOTKEY)
{
screen = IntuitionBase->ActiveScreen;
/* If the window is already open, but not in the front-most screen, close it: */
if(window)
if(window->WScreen != screen) cleanup(NULL,-1);
else {
/* Activate and move it to front: */
WindowToFront(window);
ActivateWindow(window);
/* If the window is iconified, uniconify it: */
if(window->Height<=window->BorderTop) ZipWindow(window);
break;
}
/* The screen font can be changed: */
if(checked == &newmenu[1]) font = screen->RastPort.Font;
/* If something goes wrong, change the font: */
if( setup() ) Handle_menu(13);
ScreenToFront(screen);
}
break;
case CXM_COMMAND:
switch(msgid)
{
case CXCMD_DISABLE:
/* If user want to disable the commo, iconify the window: */
if(window->Height>window->BorderTop) ZipWindow(window);
ActivateCxObj(broker, 0L);
break;
case CXCMD_ENABLE:
/* If user want to enable the commo, uniconify it: */
if(window->Height<=window->BorderTop) ZipWindow(window);
ActivateCxObj(broker, 1L);
break;
case CXCMD_APPEAR: if(window==NULL && setup())
Handle_menu(13); break;
case CXCMD_DISAPPEAR:if(window) cleanup(NULL,-1); break;
case CXCMD_KILL:
case CXCMD_UNIQUE:
/* Commodities Exchange can be told not only to refuse to launch a **
** commodity with a name already in use but also can notify the **
** already running commodity that it happened. It does this by **
** sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE. If the **
** user tries to run a windowless commodity that is already running, **
** the user wants the commodity to shut down. */
cleanup(0,0);
}
}
}
}
/**** Handle gadget messages ****/
void Handle_gadget( struct Gadget *G )
{
extern void *clipdev;
extern UBYTE GadDisable;
/* If clipboard is unavailable: */
if(G->GadgetID<3 && !clipdev && !(clipdev=(void *)CBOpen(0))) {
OffGadget(G, window, NULL);
GadDisable |= 3;
return;
}
switch(G->GadgetID)
{
case 1: /* Copy string into clipboard: */
CBWriteFTXT(clipdev, StrBuf);
break;
case 2: /* Read string from clipboard: */
if( CBQueryFTXT(clipdev) )
{
CBReadCHRS(clipdev, StrBuf, sti(gad)->MaxChars);
RefreshGList(gad, window, NULL, 1);
}
break;
case 3: /* Clear everything in the string gadget */
Handle_menu(14);
break;
case 4: /* Choose a different font */
Handle_menu(13);
}
}
/**** Main loop, which collects and distributes all messages: ****/
void handle_input(void)
{
static UBYTE buffer[8];
UWORD HelpWin=FALSE;
ULONG sigrcvd;
FOREVER {
Deb: sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag | sigwin);
/* Look from where the signal has been launched: */
if(sigrcvd & SIGBREAKF_CTRL_C) cleanup(0,0);
if(sigrcvd & cxsigflag) Handle_commo();
if((sigrcvd & sigwin) == 0) continue;
/* Use the new GadTools GT_GetIMsg() function to get input events */
while (msg = (void *) GT_GetIMsg(window->UserPort))
{
/* Copy entire message: */
CopyMem(msg,&message,sizeof(message));
/* Is it a mouse button or a menu call? */
if( message.Code == MENUHOT && (IsDraw || (Y>=ydeb && Y<=yfin && X>=xdeb && X<=xfin)) &&
window->Height>window->BorderTop)
{
/* The right mouse button has been pressed over the ASCII table: */
((struct IntuiMessage *)msg)->Code=MENUCANCEL;
message.Class=MOUSEBUTTONS;
window->Flags |= RMBTRAP;
}
/* Reply to the message */
GT_ReplyIMsg(msg);
X=message.MouseX; Y=message.MouseY;
switch(message.Class)
{
/* The close-window gad. simply quit: */
case CLOSEWINDOW: cleanup(NULL,0);
case MOUSEBUTTONS:
switch(message.Code)
{
/* Draw a recessed box below the mouse: */
case SELECTDOWN: if(HelpWin==FALSE) Handle_box(); break;
/* Clear the box and add the char. in string gadget: */
case SELECTUP:
if(IsDraw) {
INS:if(NumChar>=0 && IsDraw) {
struct StringInfo *st = sti(gad);;
if(st->NumChars>=st->MaxChars-1) strcpy(StrBuf, StrBuf+1);
strcat(st->Buffer,Char);
RefreshGList(gad, window, NULL, 1);
/* If char has been keyed in, don't clear the cursor: */
if(IsDraw==KEYB_CONTROL) break;
}
Xc=X; Yc=Y; CL:X=Y=0; Handle_box(); IsDraw=NOT_PRESSED;
}
break;
/* Draw a little window and show information on the char.: */
case MENUHOT:
if(IsDraw) goto CL;
else {
Handle_box();
if(NumChar>=0) { HelpWin=TRUE; Open_helpwin(NumChar,X-1,Y-1); }
else window->Flags &= ~RMBTRAP;
IsDraw=NOT_PRESSED;
}
break;
/* Clear the help window: */
case MENUUP:
window->Flags &= ~RMBTRAP;
if(HelpWin) { HelpWin=FALSE; Close_helpwin(); goto CL; }
}
break;
case MOUSEMOVE: if(IsDraw>0 && !HelpWin) Handle_box(); break;
case MENUPICK:
Handle_menu( GTMENUITEM_USERDATA((struct MenuItem *) ItemAddress(menu,message.Code)) );
break;
case RAWKEY: /* Rawkey which will be Translated */
/* If the rawkey code can be processed, don't translate it: */
if(message.Code>127) break; Handle_keyboard(message.Code);
ie.ie_Code = message.Code;
/* Make sure deadkeys and qualifiers are take into account: */
ie.ie_EventAddress = *((APTR *)message.IAddress);
ie.ie_Qualifier = message.Qualifier;
/* Map RAWKEY to ANSI */
if(MapRawKey(&ie, buffer, 8, NULL) <= 0) break;
# define code PopWin
code = *buffer;
/* Space bar inserts the highlighted char in the string gadget: */
if(code==' ') goto INS;
if(code==27 && IsDraw) goto CL;
/* ESC hide the interface, whilst SHIFT ESC, quit the programm: */
if(code==27) cleanup(NULL,IconBase && !(ie.ie_Qualifier&IEQUALIFIER_LSHIFT)?-1:0);
/* Remove the last inputed char or clear all the string gadget: */
if(code=='\b' || code==127) {
register WORD n=(code=='\b'?sti(gad)->NumChars-1:0);
if(n<0) break;
StrBuf[n]=0;
RefreshGList(gad, window, NULL, 1);
}
break;
case GADGETUP:
Handle_gadget( (struct Gadget *)message.IAddress );
break;
case REFRESHWINDOW:
/* A iconified window has been poped-up: */
if(window->Height>window->BorderTop) Draw_ASCIIChart();
}
/* Has the user hiden the window ? */
if(window==NULL) goto Deb;
}
}
}